home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 6 / FM Towns Free Software Collection 6.iso / ms_dos / dsort / dstmain.asm < prev    next >
Encoding:
Assembly Source File  |  1993-07-08  |  48.1 KB  |  1,612 lines

  1.     page    96,132
  2. ;§∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞§
  3. ;§                                                                          §
  4. ;§              ディレクトリエントリ  ソート  ユーティリティ                §
  5. ;§                                                                          §
  6. ;§                                     DSORT.EXE  Ver1.30    §
  7. ;§                                                                          §
  8. ;§              Copyright (C) by 福地 邦雄 1991-1992. All rights reserved.  §
  9. ;§∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞§
  10.     .MODEL  SMALL,C
  11. ;
  12.     DPB struc
  13. drivenumber     db      ?       ;ドライブ番号
  14. unitnumber      db      ?       ;ユニット番号
  15. sectorlength    dw      ?       ;セクタ長
  16. sectorperalloc  db      ?       ;1クラスタ当たりのセクタ数-1
  17. shiftcount      db      ?       ;1クラスタ当たりのセクタ数の2のべき乗
  18. reservedsector  dw      ?       ;先頭のリザーブセクタ数
  19. numberoffat     db      ?       ;FAT数
  20. directoryentry  dw      ?       ;ルートディレクトリのエントリ数
  21. datastartsector dw      ?       ;データ領域開始セクタ番号
  22. datasector      dw      ?       ;最大クラスタ番号(全クラスタ数+1)
  23. fatsector       dw      ?       ;1FAT当たりのセクタ数
  24. directorystart  dw      ?       ;ディレクトリ領域開始セクタ番号
  25. deviceheader    dd      ?       ;デバイスヘッダへのポインタ
  26. mediadescriptor db      ?       ;メディアディスクリプタ
  27. diskchange      db      ?       ;ディスクの交換可能属性
  28. tonextdpb       dd      ?       ;次のDPBへのポインタ
  29. currentcluster  dw      ?       ;カレントクラスタ
  30. reserved        db  3 dup(?)    ;リザーブ
  31.     DPB ends
  32. ;
  33.     DPB3 struc
  34. DPB3reserv      db  15 DUP(?)   ;ドライブ番号~最大クラスタ番号
  35. D3fatsector       db      ?       ;1FAT当たりのセクタ数
  36. D3directorystart  dw      ?       ;ディレクトリ領域開始セクタ番号
  37. D3deviceheader    dd      ?       ;デバイスヘッダへのポインタ
  38. D3mediadescriptor db      ?       ;メディアディスクリプタ
  39. D3diskchange      db      ?       ;ディスクの交換可能属性
  40. D3tonextdpb       dd      ?       ;次のDPBへのポインタ
  41. D3currentcluster  dw      ?       ;カレントクラスタ
  42. D3reserved        dd      ?       ;リザーブ
  43.     DPB3 ends
  44. ;
  45.     DEVHEAD struc
  46. nextdevice      dd      ?       ; 次のデバイスヘッダへのポインタ
  47. deviceattr      dw      ?       ; デバイス属性
  48. strategy        dw      ?       ; ストラテジエントリオフセット
  49. intrentry       dw      ?       ; 割り込みエントリオフセット
  50. devicename      db  8 dup(?)    ; デバイス名/ドライブ数
  51.     DEVHEAD ends
  52. ;
  53.     DSKPACKET   struc
  54. sectornum       dd      ?       ; 32bitセクタ番号
  55. rwcount         dw      ?       ; READ/WRITEセクタ数
  56. dskbuffer       dd      ?       ; バッファアドレス
  57.     DSKPACKET   ends
  58. ;
  59. YES     equ     1
  60. NO      equ     0
  61. OS2     equ     -1
  62. FAT12   equ     0ff7h
  63. FAT16   equ     0fff7h
  64. SECTOR32    equ 0000000000000010B
  65. direntrysize    equ 20h
  66. ;
  67.     extrn   sweep:word,sortexec:word,recursive:word,dirgather:word
  68.     extrn   dta:dword,srchname:dword,namebuff:dword,namebuffsiz:word
  69.     extrn   dirtype:word,fattype:word,attribute:word,clustcount:word
  70.     extrn   driveno:word,clustsize:word
  71.     extrn   fatbuff:word,dirbuff:word,sortbuff:word,sortcount:word
  72.     extrn   drvinf:byte,clustsect:word,sectcount:word,fatdrive:word
  73.     extrn   sortfuncs:word,subchain:word,wildcard:byte,pathbuff:byte
  74.     extrn   usagemsg:byte,entrycount:word,movecount:word,subsearch:word
  75.     extrn   procs:byte,dirover:byte
  76.     extrn   bothmsg:byte,sortmsg:byte,movemsg:byte,nothmsg:byte
  77.     extrn   errorno:word
  78. ;
  79.     extrn   dos4:word,sect32:word,diskaccs:byte
  80. ;
  81.     extrn   getargs:near,options:near,usageout:near,abort:near,dosstdout:near
  82.     extrn   dirlist:near,dirfind:near,strcopywild:near
  83.     extrn   dosallocx:near,dirqsort:near,inttoasc0:near
  84. ;
  85.     PUBLIC  main,sortproc,getdirinfo,getdpb,readdirectory,readrootdir,readfat
  86.     PUBLIC  getfat12chain,getfat16chain,readsubdir,selection,remainsweep
  87.     PUBLIC  copyback,filldeleted,writerootdirectory,writesubdirectory
  88.     PUBLIC  dspdirname,dspmsgend,altint23h,critical,breakflag,orgint23h
  89. ;
  90.     .code
  91. ;
  92. ;------------------------------------------------------------------------------
  93. ;   書き込み時のCtrl+C押下によるディレクトリ破壊を防ぐ処理のワーク
  94. ;------------------------------------------------------------------------------
  95. ;
  96. critical    dw  NO
  97. breakflag   dw  NO
  98. orgint23h   dd  0
  99. prgname     db  'DirSort',0     ; これは別に意味なし
  100. ;
  101. ;------------------------------------------------------------------------------
  102. ;
  103. ;   main
  104. ;       ディレクトリエントリソートユーティリティ メインプログラム
  105. ;
  106. ;   dsort   <options>   directory name
  107. ;
  108. ;   IN      ds & es PSP セグメント
  109. ;   OUT     ?
  110. ;
  111. ;------------------------------------------------------------------------------
  112. ;
  113. main        proc    near
  114. ;
  115.     call    getargs                 ; コマンド行パラメータを引き数リストに変換
  116. ;   @if (zf,on)
  117.       jnz   @i0001
  118.         jmp     usageout            ; 引き数なしの時はヘルプメッセージ
  119. ;   @ifend
  120. @i0001:
  121.     push    ax
  122.     mov     ax,_data                ; DS 設定
  123.     mov     ds,ax
  124. ;
  125.     mov     ah,30h                  ; DOS バージョンチェック
  126.     int     21h
  127. ;   @if (al,>=,4),S                 ; 4.00以上OS/2互換BOX未満ならフラグセット
  128.       cmp   al,4
  129.       jb    @i0002
  130. ;       @if (al,<,10),S
  131.           cmp   al,10
  132.           jae   @i0003
  133.             mov     dos4,YES
  134. ;       @else
  135.           jmp short @i0004
  136. @i0003:
  137.             mov     dos4,OS2
  138. ;       @ifend
  139. @i0004:
  140. ;   @else
  141.       jmp short @i0005
  142. @i0002:
  143.         mov     dos4,NO
  144. ;   @ifend
  145. @i0005:
  146. ;
  147.     mov     ax,1000h                ; ディレクトリ名バッファの獲得
  148.     xor     dx,dx                   ; 4KB
  149.     call    dosallocx
  150.     mov     word ptr namebuff+2,ax
  151. ;
  152.     mov     ax,3523h                ; Ctrl+C ベクタ取得
  153.     int     21h
  154.     mov     word ptr cs:orgint23h,bx
  155.     mov     word ptr cs:orgint23h+2,es
  156.     mov     bx,ds                   ; DS セーブ
  157.     mov     es,bx
  158.     mov     ax,2523h                ; Ctrl+C ベクタ置き換え
  159.     mov     dx,offset altint23h     ;
  160.     mov     bx,cs
  161.     mov     ds,bx
  162.     int     21h
  163.     mov     bx,es                   ; DS リストア
  164.     mov     ds,bx
  165.     pop     ax
  166. ;
  167.     call    options                 ; 引き数評価&対象ディレクトリリスト作成
  168. ;   @if (sortexec,/=,NO),or,(sweep,/=,NO)
  169.       cmp   sortexec,NO
  170.       jne   @i0006
  171.       cmp   sweep,NO
  172.       je    @i0007
  173. @i0006:
  174. ;       @if (recursive,=,YES)       ; 再帰呼び出しをおこなうか?
  175.           cmp   recursive,YES
  176.           jne   @i0008
  177.             mov     es,word ptr namebuff+2
  178.             mov     bx,800h         ; ディレクトリ名バッファのサイズ変更
  179.             mov     ah,4ah          ; 32KB
  180.             int     21h
  181. ;           @if (cf,off)
  182.               jc    @i0009
  183.                 add     namebuffsiz,7000h
  184. ;           @ifend
  185. @i0009:
  186. ;       @ifend
  187. @i0008:
  188.         push    namebuffsiz         ; パラメータセット
  189.         push    word ptr namebuff
  190.         push    word ptr namebuff+2
  191.         xor     ax,ax
  192.         push    ax
  193.         call    sortproc            ; ディレクトリソート実行
  194. ;   @ifend
  195. @i0007:
  196. ;
  197.     mov     ax,2523h                ; Ctrl+C ベクタ復元
  198.     lds     dx,cs:orgint23h
  199.     int     21h
  200. ;
  201.     mov     ah,0dh              ; ディスクバッファ リセット
  202.     int     21h
  203. ;
  204.     mov     ax,4c00h                ; プログラム終了
  205.     int     21h
  206. ;
  207. main        endp
  208. ;
  209. ;------------------------------------------------------------------------------
  210. ;
  211. ;   sortproc
  212. ;       ディレクトリソートを実行する
  213. ;
  214. ;   TYPE    near call
  215. ;   IN      sp+2:ディレクトリ名リストアドレス
  216. ;           sp+6:ディレクトリ名バッファの空き領域の先頭
  217. ;           sp+8:ディレクトリ名バッファの空き領域サイズ
  218. ;   OUT     なし
  219. ;   保存レジスタ ds
  220. ;
  221. ;------------------------------------------------------------------------------
  222. ;
  223. sortproc    proc    near    curnameoff,curnameseg,freenameoff,freenamesiz
  224. ;
  225.     mov     di,curnameoff
  226.     mov     es,curnameseg
  227. ;   @do until
  228. @d0001:
  229.         mov     entrycount,0        ; 処理したエントリのカウンタを初期化
  230.         mov     sortcount,0
  231.         mov     movecount,0
  232.         mov     ah,0dh              ; ディスクバッファ リセット
  233.         int     21h
  234. ;
  235.         call    getdirinfo          ; ディレクトリ情報獲得
  236. ;       @if (zf,on),L
  237.           jz    @i0010
  238.           jmp   @i0011
  239. @i0010:
  240.             mov     di,curnameoff   ; ディレクトリ名表示
  241.             mov     es,curnameseg
  242.             call    dspdirname
  243.             call    readdirectory   ; ディレクトリ読み込み
  244. ;           @if (zf,on)
  245.               jnz   @i0012
  246. ;               @if (sortexec,=,YES),S
  247.                   cmp   sortexec,YES
  248.                   jne   @i0013
  249.                     call    selection   ; ソート対象エントリ取り出し
  250. ;                   @if (ax,>,1)
  251.                       cmp   ax,1
  252.                       jbe   @i0014
  253.                         push    ds
  254.                         mov     ax,ds
  255.                         mov     es,ax
  256.                         mov     ax,offset sortfuncs
  257.                         push    ax
  258.                         push    sortcount
  259.                         push    sortbuff
  260.                         call    dirqsort    ; クイックソート
  261.                         pop ds
  262. ;                   @ifend
  263. @i0014:
  264. ;                   @if (sweep,=,YES)
  265.                       cmp   sweep,YES
  266.                       jne   @i0015
  267.                         call    remainsweep ; ソート対象外エントリを掻き集める
  268. ;                   @ifend
  269. @i0015:
  270.                     call    copyback    ; ソートしたエントリを戻す
  271. ;               @else
  272.                   jmp short @i0016
  273. @i0013:
  274.                     call    predelete
  275.                     call    remainsweep
  276. ;               @ifend
  277. @i0016:
  278.                 call    filldeleted     ; 削除エントリの情報をクリアする
  279.                 mov     cs:critical,YES ; クリティカルセクション開始
  280. ;               @if (dirtype,=,0),S
  281.                   cmp   dirtype,0
  282.                   jne   @i0017
  283.                     call    writerootdirectory  ; ルートディレクトリ書き込み
  284. ;               @else
  285.                   jmp short @i0018
  286. @i0017:
  287.                     call    writesubdirectory   ; サブディレクトリ書き込み
  288. ;               @ifend
  289. @i0018:
  290.                 mov     es,dirbuff              ; ディレクトリバッファの開放
  291.                 mov     ah,49h
  292.                 int     21h
  293.                 call    dspmsgend       ; 終了メッセージ表示
  294.                 mov     cs:critical,NO  ; クリティカルセクション終了
  295. ;               @if (cs:breakflag,=,YES)    ; Ctrl+Cが押下されたので終了
  296.                   cmp   cs:breakflag,YES
  297.                   jne   @i0019
  298.                     mov     errorno,-1
  299.                     xor     cx,cx
  300.                     xor     dx,dx
  301.                     jmp     abort
  302. ;               @ifend
  303. @i0019:
  304. ;           @ifend
  305. @i0012:
  306. ;           @if (recursive,=,YES)   ; 再帰呼び出し
  307.               cmp   recursive,YES
  308.               jne   @i0020
  309.                 mov     ah,0dh      ; ディスクバッファ リセット
  310.                 int     21h
  311. ;
  312.                 mov     subsearch,YES   ;
  313.                 mov     di,curnameoff   ; サブディレクトリのリスト獲得
  314.                 mov     es,curnameseg
  315.                 call    strcopywild
  316.                 mov     word ptr srchname,di
  317.                 mov     word ptr srchname+2,es
  318.                 call    dirlist
  319.                 mov     ax,word ptr namebuff
  320. ;               @if (ax,/=,freenameoff) ; サブディレクトリ有りの時
  321.                   cmp   ax,freenameoff
  322.                   je    @i0021
  323.                     push    namebuffsiz
  324.                     push    ax
  325.                     push    word ptr namebuff+2
  326.                     push    freenameoff
  327.                     call    sortproc    ; ディレクトリソート再帰実行
  328. ;               @ifend
  329. @i0021:
  330.                 mov     si,freenameoff  ; 各ワーク情報を再帰実行から戻す
  331.                 mov     es,freenamesiz
  332.                 mov     namebuffsiz,es
  333.                 mov     word ptr namebuff,si
  334.                 mov     es,curnameseg
  335.                 mov     word ptr es:[si],0
  336.                 mov     subsearch,NO    ;
  337. ;           @ifend
  338. @i0020:
  339. ;       @ifend
  340. @i0011:
  341.         mov     di,curnameoff       ; 次の対象ディレクトリへ
  342.         mov     es,curnameseg
  343.         cld
  344.         xor     ax,ax
  345.         mov     cx,-1
  346.       repne scasb
  347.         mov     curnameoff,di
  348. ;   @doend (byte ptr es:[di],=,0),L ; ディレクトリリストの終了か?
  349.       cmp   byte ptr es:[di],0
  350.       je    @d0002
  351.       jmp   @d0001
  352. @d0002:
  353. ;
  354.     ret     8
  355. ;
  356. sortproc    endp
  357. ;
  358. ;------------------------------------------------------------------------------
  359. ;
  360. ;   getdirinfo
  361. ;       ディレクトリ及びその所属するドライブの情報を獲得する
  362. ;
  363. ;   TYPE    near call
  364. ;   IN      ds:di = ディレクトリ名
  365. ;   OUT     drvinf = DPBのコピー  その他 ディレクトリ情報
  366. ;   保存レジスタ bx,cx,dx,si,di,bp,ds,es
  367. ;
  368. ;------------------------------------------------------------------------------
  369. ;
  370. getdirinfo  proc    near
  371. ;
  372.     call    dirfind
  373. ;   @if (zf,on)
  374.       jnz   @i0022
  375.         mov     dirtype,ax          ; ディレクトリタイプ ルート/サブ
  376.         mov     subchain,ax         ; FATチェインの先頭
  377.         mov     driveno,dx          ; ドライブ番号
  378.         dec     driveno
  379. ;
  380.         mov     di,offset drvinf    ; Drive Parameter Block 取得
  381.         call    getdpb
  382. ;       @if (zf,on)
  383.           jnz   @i0023
  384. ;           @if (drvinf.datasector,<=,4086),S    ; 12bitFAT/16bitFAT
  385.               cmp   drvinf.datasector,4086
  386.               ja    @i0024
  387.                 mov     fattype,FAT12            ;   v1.00バグ '='が無かった
  388. ;           @else
  389.               jmp short @i0025
  390. @i0024:
  391.                 mov     fattype,FAT16
  392. ;           @ifend
  393. @i0025:
  394.             xor     ax,ax
  395.             mov     al,drvinf.sectorperalloc
  396.             inc     ax
  397.             mov     clustsect,ax        ; 1クラスタ当たりのセクタ数
  398.             mul     drvinf.sectorlength
  399.             mov     clustsize,ax        ; 1クラスタのバイトサイズ
  400.             les     bx,drvinf.deviceheader ; デバイスドライバ属性テスト
  401. ;           @if (dos4,=,OS2),or,(es:[bx].deviceattr,on,SECTOR32),S
  402.               cmp   dos4,OS2
  403.               je    @i0026
  404.               test  es:[bx].deviceattr,SECTOR32
  405.               jz    @i0027
  406. @i0026:
  407.                 mov     sect32,YES      ; 32bitセクタ番号サポート
  408. ;           @else
  409.               jmp short @i0028
  410. @i0027:
  411.                 mov     sect32,NO
  412. ;           @ifend
  413. @i0028:
  414.             xor     ax,ax
  415. ;       @ifend
  416. @i0023:
  417. ;   @ifend
  418. @i0022:
  419.     ret
  420. ;
  421. getdirinfo  endp
  422. ;
  423. ;------------------------------------------------------------------------------
  424. ;
  425. ;   getdpb
  426. ;       ドライブパラメータブロックをコピーする
  427. ;
  428. ;   TYPE    near call
  429. ;   IN      dl = ドライブ番号 A:1 B:2 ...
  430. ;           ds:di = drive parameter block をコピーする領域のアドレス
  431. ;           ds:dos4 DOS V4.xx以上フラグ
  432. ;   OUT     ax = 完了コード
  433. ;   保存レジスタ bx,cx,dx,si,di,bp,ds,es
  434. ;
  435. ;------------------------------------------------------------------------------
  436. ;
  437. getdpb      proc    near    uses bx cx si di ds es
  438. ;
  439.     cld
  440.     mov     ax,ds                   ; DS セーブ
  441.     mov     es,ax
  442.     mov     ah,32h                  ; DPBアドレス取得 非公開
  443.     int     21h
  444. ;   @if (al,=,0),S
  445.       or    al,al
  446.       jne   @i0029
  447.         mov     cx,11h                  ; DPB コピー 34バイト
  448.         mov     si,bx
  449.         push    di
  450.       rep   movsw                       ; DPB コピー
  451.         pop     di
  452. ;       @if (es:dos4,/=,YES) ; DOS V3.xx以下のときFATセクタ数が1バイトなので
  453.           cmp   es:dos4,YES
  454.           je    @i0030
  455.             lea     si,[bx].D3directorystart ; 後ろに1バイト移動コピーする
  456.             lea     di,[di].directorystart
  457.             mov     cx,8
  458.           rep   movsw
  459.             and     es:drvinf.fatsector,0FFH ; 移動後のゴミをクリア
  460. ;       @ifend
  461. @i0030:
  462.         xor     ax,ax
  463. ;   @else
  464.       jmp short @i0031
  465. @i0029:
  466.         test    ax,ax
  467. ;   @ifend
  468. @i0031:
  469.     ret
  470. ;
  471. getdpb      endp
  472. ;
  473. ;------------------------------------------------------------------------------
  474. ;
  475. ;   readdirectory
  476. ;       ディレクトリを読み込む
  477. ;
  478. ;   TYPE    near call
  479. ;   IN      dirtype,driveno,drvinf構造体,fatdrive
  480. ;   OUT     ax = 完了コード     entrycount,clustcount
  481. ;   保存レジスタ bx,cx,dx,di,bp,ds
  482. ;
  483. ;------------------------------------------------------------------------------
  484. ;
  485. readdirectory   proc    near
  486. ;
  487. ;   @if (dirtype,=,0),S             ; ルートディレクトリ
  488.       cmp   dirtype,0
  489.       jne   @i0032
  490.         mov     ax,drvinf.directoryentry
  491.         mov     entrycount,ax       ; ディレクトリエントリ数 格納
  492.         call    readrootdir
  493. ;   @else
  494.       jmp short @i0033
  495. @i0032:
  496.         mov     ax,driveno          ; サブディレクトリ
  497. ;       @if (ax,/=,fatdrive)        ; 読み込み済FATと違うドライブ名の時
  498.           cmp   ax,fatdrive
  499.           je    @i0034
  500.             call    readfat         ; FAT読み込み
  501. ;       @ifend
  502. @i0034:
  503. ;
  504.         cld                         ; サブディレクトリのクラスタチェインを獲得
  505.         mov     di,offset subchain
  506.         mov     es,fatbuff
  507. ;       @if (fattype,=,FAT12),S
  508.           cmp   fattype,FAT12
  509.           jne   @i0035
  510.             call    getfat12chain
  511. ;       @else
  512.           jmp short @i0036
  513. @i0035:
  514.             call    getfat16chain
  515. ;       @ifend
  516. @i0036:
  517. ;       @if (dx,>=,1026),S
  518.           cmp   dx,1026
  519.           jb    @i0037
  520.             mov     ah,9            ; ディレクトリサイズオーバー表示
  521.             mov     dx,offset dirover
  522.             int     21h
  523.             mov     ax,-1
  524. ;       @else
  525.           jmp short @i0038
  526. @i0037:
  527.             mov     clustcount,dx   ; サブディレクトリのクラスタ数を設定
  528.             mov     ax,dx
  529.             mul     clustsize
  530.             mov     cx,32           ; ディレクトリエントリ数 計算 格納
  531.             div     cx
  532.             mov     entrycount,ax
  533.             call    readsubdir      ; サブディレクトリ読み込み
  534. ;       @ifend
  535. @i0038:
  536. ;   @ifend
  537. @i0033:
  538. rdirerror:
  539.     test    ax,ax
  540.     ret
  541. ;
  542. readdirectory   endp
  543. ;
  544. ;------------------------------------------------------------------------------
  545. ;
  546. ;   readrootdir
  547. ;       ルートディレクトリの内容をメモリに読み込む
  548. ;
  549. ;   TYPE    near call
  550. ;   IN      drive parameter block 領域
  551. ;   OUT     dirbuff = 読み込んだディレクトリのセグメントアドレス
  552. ;   保存レジスタ bp,ds,es
  553. ;
  554. ;------------------------------------------------------------------------------
  555. ;
  556. readrootdir     proc    near
  557.     local rdsect:word,dirlen:word,buffseg:word,maxrdsect:word
  558. ;
  559.     mov     ax,drvinf.datastartsector ; ディレクトリサイズ計算とメモリ獲得
  560.     sub     ax,drvinf.directorystart
  561.     mov     sectcount,ax
  562.     mul     drvinf.sectorlength
  563.     call    dosallocx
  564.     mov     dirbuff,ax
  565. ;
  566.     mov     ax,drvinf.directorystart ; ルートディレクトリ読み込み
  567.     mov     rdsect,ax               ; 読み込み開始セクタ番号
  568.     mov     ax,sectcount
  569.     mov     dirlen,ax               ; 残りディレクトリセクタ数
  570.     mov     ax,dirbuff
  571.     mov     buffseg,ax              ; 読み込みバッファセグメント
  572.     mov     dx,1
  573.     xor     ax,ax
  574.     div     drvinf.sectorlength
  575.     mov     maxrdsect,ax            ; 64KB当たりのセクタ数
  576. ;   @do while,(dirlen,/=,0)         ; 読み込みループ 残りセクタ数0まで
  577. @d0003:
  578.       cmp   dirlen,0
  579.       je    @d0004
  580.         mov     ax,driveno
  581.         mov     cx,maxrdsect
  582. ;       @if (cx,<=,dirlen),S        ; 残りセクタ数が64KB以上なら
  583.           cmp   cx,dirlen
  584.           ja    @i0039
  585.             sub     dirlen,cx       ; 残りセクタ数を更新
  586. ;       @else                       ; 64KB未満なら
  587.           jmp short @i0040
  588. @i0039:
  589.             xor     cx,cx           ; セクタ数を獲得してワークには0を入れる
  590.             xchg    dirlen,cx
  591. ;       @ifend
  592. @i0040:
  593.         mov     dx,rdsect           ; 開始セクタ数獲得
  594.         push    bp                  ; 読み込み
  595.         push    ds
  596. ;       @if (sect32,=,NO),S         ; 従来の16bitセクタ番号
  597.           cmp   sect32,NO
  598.           jne   @i0041
  599.             xor     bx,bx
  600.             mov     ds,buffseg
  601. ;       @else                       ; 新規の32bitセクタ番号
  602.           jmp short @i0042
  603. @i0041:
  604.             mov     bx,offset diskaccs
  605.             mov     word ptr [bx].sectornum,dx
  606.             mov     word ptr [bx].sectornum+2,0
  607.             mov     [bx].rwcount,cx
  608.             mov     cx,buffseg
  609.             mov     word ptr [bx].dskbuffer,0
  610.             mov     word ptr [bx].dskbuffer+2,cx
  611.             mov     cx,-1
  612. ;       @ifend
  613. @i0042:
  614.         int     25h
  615. ;       @if (cf,on)
  616.           jnc   @i0043
  617.             xor     cx,cx
  618.             xor     dx,dx
  619.             jmp     abort
  620. ;       @ifend
  621. @i0043:
  622.         popf
  623.         pop     ds
  624.         pop     bp
  625. ;
  626.         mov     ax,maxrdsect        ; 読み込み開始セクタ数更新
  627.         add     rdsect,ax
  628.         add     buffseg,1000h       ; 読み込みバッファセグメント更新
  629. ;   @doend
  630.       jmp   @d0003
  631. @d0004:
  632.     xor     ax,ax
  633.     ret
  634. ;
  635. readrootdir     endp
  636. ;
  637. ;------------------------------------------------------------------------------
  638. ;
  639. ;   readfat
  640. ;       FATを読み込むための領域を獲得し、FATを読み込む
  641. ;
  642. ;   TYPE    near call
  643. ;   IN      drive parameter block 領域
  644. ;   OUT     fatbuff = 読み込んだFATのセグメントアドレス
  645. ;   保存レジスタ bp,ds,es
  646. ;
  647. ;------------------------------------------------------------------------------
  648. ;
  649. readfat     proc    near
  650.     local rdsect:word,fatlen:word,buffseg:word,maxrdsect:word
  651. ;
  652. ;   @if (fatdrive,/=,-1)            ; 既に別のFATを読み込み済の時、解放する
  653.       cmp   fatdrive,-1
  654.       je    @i0044
  655.         mov     ah,49h              ; メモリ解放FUNC 未設定のバグ
  656.         mov     es,fatbuff
  657.         int     21h
  658.         mov     fatdrive,-1
  659.         mov     fatbuff,0
  660. ;   @ifend
  661. @i0044:
  662.     mov     ax,drvinf.fatsector     ; FAT用領域獲得
  663.     mul     drvinf.sectorlength
  664.     call    dosallocx
  665.     mov     fatbuff,ax
  666. ;
  667.     mov     ax,driveno              ; 128KB BIG-FAT対応
  668.     mov     fatdrive,ax
  669.     mov     ax,drvinf.reservedsector ; ワーク設定
  670.     mov     rdsect,ax               ; 読み込み開始セクタ番号
  671.     mov     ax,drvinf.fatsector
  672.     mov     fatlen,ax               ; 残りFATセクタ数
  673.     mov     ax,fatbuff
  674.     mov     buffseg,ax              ; 読み込みバッファセグメント
  675.     mov     dx,1
  676.     xor     ax,ax
  677.     div     drvinf.sectorlength
  678.     mov     maxrdsect,ax            ; 64KB当たりのセクタ数
  679. ;   @do while,(fatlen,/=,0)         ; FAT読み込みループ 残りセクタ数0まで
  680. @d0005:
  681.       cmp   fatlen,0
  682.       je    @d0006
  683.         mov     ax,driveno
  684.         mov     cx,maxrdsect
  685. ;       @if (cx,<=,fatlen),S        ; 残りFATセクタ数が64KB以上なら
  686.           cmp   cx,fatlen
  687.           ja    @i0045
  688.             sub     fatlen,cx       ; 残りFATセクタ数を更新
  689. ;       @else                       ; 64KB未満なら
  690.           jmp short @i0046
  691. @i0045:
  692.             xor     cx,cx           ; セクタ数を獲得してワークには0を入れる
  693.             xchg    fatlen,cx
  694. ;       @ifend
  695. @i0046:
  696.         mov     dx,rdsect           ; 開始セクタ数獲得
  697.         push    bp                  ; FAT読み込み
  698.         push    ds
  699. ;       @if (sect32,=,NO),S         ; 従来の16bitセクタ番号
  700.           cmp   sect32,NO
  701.           jne   @i0047
  702.             xor     bx,bx
  703.             mov     ds,buffseg
  704. ;       @else                       ; 新規の32bitセクタ番号
  705.           jmp short @i0048
  706. @i0047:
  707.             mov     bx,offset diskaccs
  708.             mov     word ptr [bx].sectornum,dx
  709.             mov     word ptr [bx].sectornum+2,0
  710.             mov     [bx].rwcount,cx
  711.             mov     cx,buffseg
  712.             mov     word ptr [bx].dskbuffer,0
  713.             mov     word ptr [bx].dskbuffer+2,cx
  714.             mov     cx,-1
  715. ;       @ifend
  716. @i0048:
  717.         int     25h
  718. ;       @if (cf,on)
  719.           jnc   @i0049
  720.             xor     cx,cx
  721.             xor     dx,dx
  722.             jmp     abort
  723. ;       @ifend
  724. @i0049:
  725.         popf
  726.         pop     ds
  727.         pop     bp
  728. ;
  729.         mov     ax,maxrdsect        ; 読み込み開始セクタ数更新
  730.         add     rdsect,ax
  731.         add     buffseg,1000h       ; 読み込みバッファセグメント更新
  732. ;   @doend
  733.       jmp   @d0005
  734. @d0006:
  735.     ret
  736. ;
  737. readfat     endp
  738. ;
  739. ;------------------------------------------------------------------------------
  740. ;
  741. ;   getfat12chain
  742. ;       12ビットFATのチェインをたどって、配列に書き出す。
  743. ;
  744. ;   TYPE    near call
  745. ;   IN      es:オフセット0= FAT領域
  746. ;           ds:di = FATチェインを書き出す配列、 及びその先頭に最初のクラスタ
  747. ;           番号を格納しておくこと
  748. ;   OUT     dx = チェインの総クラスタ数
  749. ;   保存レジスタ si,bp,ds,es
  750. ;
  751. ;------------------------------------------------------------------------------
  752. ;
  753. getfat12chain   proc    near
  754. ;
  755.     mov     cl,4
  756.     xor     dx,dx
  757. ;   @do while,(word ptr [di],<,FAT12),and,(dx,<,1026)
  758. @d0007:
  759.       cmp   word ptr [di],FAT12
  760.       jae   @d0008
  761.       cmp   dx,1026
  762.       jae   @d0008
  763.         mov     bx,[di]
  764.         mov     ax,bx
  765.         shr     ax,1
  766.         add     bx,ax
  767.         mov     ax,es:[bx]
  768. ;       @if (word ptr [di],off,1),S
  769.           test  word ptr [di],1
  770.           jnz   @i0050
  771.             and     ax,0fffh
  772. ;       @else
  773.           jmp short @i0051
  774. @i0050:
  775.             shr     ax,cl
  776. ;       @ifend
  777. @i0051:
  778.         lea     di,[di+2]
  779.         mov     [di],ax
  780.         inc     dx
  781. ;   @doend
  782.       jmp   @d0007
  783. @d0008:
  784.     ret
  785. ;
  786. getfat12chain   endp
  787. ;
  788. ;------------------------------------------------------------------------------
  789. ;
  790. ;   getfat16chain
  791. ;       16ビットFATのチェインをたどって、配列に書き出す。
  792. ;
  793. ;   TYPE    near call
  794. ;   IN      es:オフセット0 = FAT領域
  795. ;           ds:di = FATチェインを書き出す配列、 及びその先頭に最初のクラスタ
  796. ;           番号を格納しておくこと
  797. ;   OUT     dx = チェインの総クラスタ数
  798. ;   保存レジスタ cx,bp,ds
  799. ;
  800. ;------------------------------------------------------------------------------
  801. ;
  802. getfat16chain   proc    near
  803. ;
  804.     mov     si,es                   ; 128KB BIG-FAT対応 FAT領域セグメント退避
  805.     xor     dx,dx
  806. ;   @do while,(word ptr [di],<,FAT16),and,(dx,<,1026)
  807. @d0009:
  808.       cmp   word ptr [di],FAT16
  809.       jae   @d0010
  810.       cmp   dx,1026
  811.       jae   @d0010
  812.         mov     bx,[di]
  813.         shl     bx,1
  814. ;       @if (cf,off),S              ; 最初の64KB
  815.           jc    @i0052
  816.             mov     es,si
  817. ;       @else                       ; 次の64KB
  818.           jmp short @i0053
  819. @i0052:
  820.             lea     ax,[si+1000h]
  821.             mov     es,ax
  822. ;       @ifend
  823. @i0053:
  824.         mov     ax,es:[bx]          ; FATチェインの獲得
  825.         lea     di,[di+2]
  826.         mov     [di],ax
  827.         inc     dx
  828. ;   @doend
  829.       jmp   @d0009
  830. @d0010:
  831.     ret
  832. ;
  833. getfat16chain   endp
  834. ;
  835. ;------------------------------------------------------------------------------
  836. ;
  837. ;   readsubdir
  838. ;       サブディレクトリを読み込む
  839. ;
  840. ;   TYPE    near call
  841. ;   IN      clustcount ディレクトリのクラスタ数
  842. ;   OUT     dirbuff = 読み込んだディレクトリのセグメントアドレス
  843. ;   保存レジスタ cx,si,bp,ds,es
  844. ;
  845. ;------------------------------------------------------------------------------
  846. ;
  847. readsubdir     proc    near
  848.     local cluster:word,clustseg:word
  849. ;
  850.     mov     dx,clustcount           ; ディレクトリサイズ計算
  851.     mov     cluster,dx
  852.     mov     ax,clustsect
  853.     mul     dx
  854.     mul     drvinf.sectorlength
  855.     call    dosallocx               ; ディレクトリバッファ獲得
  856.     mov     dirbuff,ax
  857.     mov     ax,clustsize
  858.     mov     cl,4
  859.     shr     ax,cl
  860.     mov     clustseg,ax
  861.     xor     bx,bx
  862.     mov     di,offset subchain      ; ディレクトリクラスタチェインの先頭
  863. ;
  864. ;   @if (sect32,=,NO)
  865.       cmp   sect32,NO
  866.       jne   @i0054
  867.         push    ds
  868.         mov     ax,ds
  869.         mov     es,ax
  870.         mov     ds,dirbuff
  871. ;       @do until
  872. @d0011:
  873.             mov     ax,es:[di]          ; ディレクトリクラスタ読み込み
  874.             sub     ax,2
  875.             mov     cx,es:clustsect
  876.             mul     cx
  877.             add     ax,es:drvinf.datastartsector
  878.             mov     dx,ax
  879.             mov     ax,es:driveno
  880.             push    bp
  881.             push    di
  882.             int     25h
  883. ;           @if (cf,on)
  884.               jnc   @i0055
  885.                 xor     cx,cx
  886.                 xor     dx,dx
  887.                 jmp     abort
  888. ;           @ifend
  889. @i0055:
  890.             popf
  891.             pop     di
  892.             pop     bp
  893.             mov     ax,ds
  894.             add     ax,clustseg         ; 次のバッファセグメント
  895.             mov     ds,ax
  896.             lea     di,[di+2]           ; 次のクラスタ
  897.             dec     cluster             ; カウントダウン
  898. ;       @doend (zf,on)
  899.           jnz   @d0011
  900.         pop ds
  901. ;   @else
  902.       jmp   @i0056
  903. @i0054:
  904.         mov     ax,clustsect
  905.         mov     diskaccs.rwcount,ax
  906.         mov     ax,dirbuff
  907.         mov     word ptr diskaccs.dskbuffer,0
  908.         mov     word ptr diskaccs.dskbuffer+2,ax
  909. ;       @do until
  910. @d0012:
  911.             mov     bx,offset diskaccs
  912.             mov     ax,[di]             ; ディレクトリクラスタ読み込み
  913.             sub     ax,2
  914.             mov     cx,clustsect
  915.             mul     cx
  916.             add     ax,drvinf.datastartsector
  917.             adc     dx,0
  918.             mov     word ptr [bx].sectornum,ax
  919.             mov     word ptr [bx].sectornum+2,dx
  920.             mov     ax,driveno
  921.             mov     cx,-1
  922.             push    bp
  923.             push    di
  924.             int     25h
  925. ;           @if (cf,on)
  926.               jnc   @i0057
  927.                 xor     cx,cx
  928.                 xor     dx,dx
  929.                 jmp     abort
  930. ;           @ifend
  931. @i0057:
  932.             popf
  933.             pop     di
  934.             pop     bp
  935.             mov     ax,clustseg
  936.             add     word ptr diskaccs.dskbuffer+2,ax  ; 次のバッファセグメント
  937.             lea     di,[di+2]                       ; 次のクラスタ
  938.             dec     cluster                         ; カウントダウン
  939. ;       @doend (zf,on)
  940.           jnz   @d0012
  941. ;   @ifend
  942. @i0056:
  943.     xor     ax,ax
  944.     ret
  945. ;
  946. readsubdir  endp
  947. ;
  948. ;------------------------------------------------------------------------------
  949. ;
  950. ;   selection
  951. ;       読み込んだディレクトリからattributeで指定されたエントリを選択して
  952. ;       ソートバッファに移動する
  953. ;
  954. ;   TYPE    near call
  955. ;   IN      dirbuff = 読み込んだディレクトリのセグメントアドレス その他
  956. ;   OUT     sortbuff = ソート対象を選択・移動したセグメントアドレス
  957. ;   保存レジスタ bp,ds
  958. ;
  959. ;------------------------------------------------------------------------------
  960. ;
  961. selection   proc    near
  962. ;
  963.     mov     ax,direntrysize         ; ディレクトリサイズからバッファサイズ
  964.     mul     entrycount              ;
  965.     call    dosallocx               ; ソートバッファ獲得
  966.     mov     sortbuff,ax
  967.     mov     es,ax
  968.     mov     bx,attribute            ; 選出属性
  969.     mov     dx,entrycount           ; エントリ数
  970.     mov     si,dirbuff
  971. ;   @if (dirtype,/=,0)              ; サブディレクトリの時は最初の2つを除外
  972.       cmp   dirtype,0
  973.       je    @i0058
  974.         sub     dx,2
  975.         lea     si,[si+4]
  976. ;   @ifend
  977. @i0058:
  978. ;
  979.     push    ds
  980.     cld
  981.     xor     ax,ax
  982.     mov     ds,si
  983. ;   @do while,(dx,/=,0),and,(byte ptr ds:[0],/=,0)
  984. @d0013:
  985.       or    dx,dx
  986.       je    @d0014
  987.       cmp   byte ptr ds:[0],0
  988.       je    @d0014
  989. ;       @cbegin
  990. ;       @case (byte ptr ds:[0],=,0e5h),S   ; 削除エントリか?
  991.           cmp   byte ptr ds:[0],0e5h
  992.           jne   @c0002
  993.             mov     byte ptr ds:[0],0      ; 後の処理のために0を書いておく
  994. ;       @case (byte ptr ds:[0bh],on,bl),S  ; 属性違いか?
  995.           jmp short @c0001
  996. @c0002:
  997.           test  byte ptr ds:[0bh],bl
  998.           jz    @c0003
  999. ;       @other                      ; ソートバッファへ移動
  1000.           jmp short @c0001
  1001. @c0003:
  1002.             mov     cx,10h
  1003.             xor     si,si
  1004.             xor     di,di
  1005.           rep   movsw
  1006.             mov     byte ptr ds:[0],0  ; 移動元に0を書いておく
  1007. ;           @if (byte ptr es:[0],=,5)   ; 名前の頭がE5用のコードなら戻しておく
  1008.               cmp   byte ptr es:[0],5
  1009.               jne   @i0059
  1010.                 mov     byte ptr es:[0],0e5h
  1011. ;           @ifend
  1012. @i0059:
  1013.             mov     si,es
  1014.             lea     si,[si+2]
  1015.             mov     es,si
  1016.             inc     ax              ; 移動したエントリ数を加算
  1017. ;       @cend
  1018. @c0001:
  1019.         mov     si,ds
  1020.         lea     si,[si+2]
  1021.         mov     ds,si
  1022.         dec     dx                  ; カウントダウン
  1023. ;   @doend
  1024.       jmp   @d0013
  1025. @d0014:
  1026.     pop     ds
  1027.     mov     sortcount,ax            ; 移動したエントリ数を記録
  1028.     ret
  1029. ;
  1030. selection   endp
  1031. ;
  1032. ;------------------------------------------------------------------------------
  1033. ;
  1034. ;   predelete
  1035. ;       後のremainsweepルーチンのために削除エントリの先頭を00とする
  1036. ;
  1037. ;   TYPE    near call
  1038. ;   IN      entrycount,dirbuff
  1039. ;   OUT     なし
  1040. ;   保存レジスタ ax,bx,dx,si,bp,ds
  1041. ;
  1042. ;------------------------------------------------------------------------------
  1043. ;
  1044. predelete   proc    near
  1045. ;
  1046.     mov     cx,entrycount
  1047.     mov     di,dirbuff
  1048. ;   @do until
  1049. @d0015:
  1050.         mov     es,di
  1051. ;       @if (byte ptr es:[0],=,0e5h)
  1052.           cmp   byte ptr es:[0],0e5h
  1053.           jne   @i0060
  1054.             mov     byte ptr es:[0],0
  1055. ;       @ifend
  1056. @i0060:
  1057.         lea     di,[di+2]
  1058.         dec     cx
  1059. ;   @doend (zf,on)
  1060.       jnz   @d0015
  1061.     ret
  1062. ;
  1063. predelete   endp
  1064. ;
  1065. ;------------------------------------------------------------------------------
  1066. ;
  1067. ;   remainsweep
  1068. ;       ソート対象外のエントリをディレクトリバッファの先頭に集める
  1069. ;
  1070. ;   TYPE    near call
  1071. ;   IN      entrycount,dirbuff
  1072. ;   OUT     movecount
  1073. ;   保存レジスタ ax,bp,ds
  1074. ;
  1075. ;------------------------------------------------------------------------------
  1076. ;
  1077. remainsweep proc    near
  1078. ;
  1079.     cld
  1080.     push    ds
  1081.     xor     bx,bx
  1082.     mov     dx,entrycount           ; ディレクトリのエントリサイズ
  1083.     mov     ds,dirbuff
  1084.     mov     di,ds                   ; 最初の空きエントリ位置取得
  1085. ;   @do while,(byte ptr ds:[0],/=,0),and,(dx,/=,0)
  1086. @d0016:
  1087.       cmp   byte ptr ds:[0],0
  1088.       je    @d0017
  1089.       or    dx,dx
  1090.       je    @d0017
  1091.         lea     di,[di+2]
  1092.         mov     ds,di
  1093.         dec     dx
  1094. ;   @doend
  1095.       jmp   @d0016
  1096. @d0017:
  1097.     mov     es,di
  1098. ;   @do until
  1099. @d0018:
  1100.         mov     di,ds               ; 次の有効エントリ位置取得
  1101. ;       @do while,(byte ptr ds:[0],=,0),and,(dx,/=,0)
  1102. @d0019:
  1103.           cmp   byte ptr ds:[0],0
  1104.           jne   @d0020
  1105.           or    dx,dx
  1106.           je    @d0020
  1107.             lea     di,[di+2]
  1108.             mov     ds,di
  1109.             dec     dx
  1110. ;       @doend
  1111.           jmp   @d0019
  1112. @d0020:
  1113. ;       @if (dx,/=,0)               ; 終了でなければエントリを頭へ詰める
  1114.           or    dx,dx
  1115.           je    @i0061
  1116.             inc     bx
  1117.             mov     cx,10h
  1118.             xor     si,si
  1119.             xor     di,di
  1120.           rep   movsw
  1121.             mov     byte ptr ds:[0],0 ; 移動元を空きエントリとする
  1122.             mov     di,es
  1123. ;           @do while,(byte ptr es:[0],/=,0)  ; 次の空きエントリ位置取得
  1124. @d0021:
  1125.               cmp   byte ptr es:[0],0
  1126.               je    @d0022
  1127.                 lea     di,[di+2]
  1128.                 mov     es,di
  1129. ;           @doend
  1130.               jmp   @d0021
  1131. @d0022:
  1132. ;       @ifend
  1133. @i0061:
  1134. ;   @doend (dx,=,0)
  1135.       or    dx,dx
  1136.       jne   @d0018
  1137.     pop     ds
  1138.     mov     movecount,bx            ; 移動したエントリ数を記録
  1139.     ret
  1140. ;
  1141. remainsweep endp
  1142. ;
  1143. ;------------------------------------------------------------------------------
  1144. ;
  1145. ;   copyback
  1146. ;       ソートバッファの内容をディレクトリバッファへ書き戻す
  1147. ;
  1148. ;   TYPE    near call
  1149. ;   IN      sortcount,sortbuff,dirbuff
  1150. ;   OUT     dirbuff
  1151. ;   保存レジスタ    bx,bp,ds
  1152. ;
  1153. ;------------------------------------------------------------------------------
  1154. ;
  1155. copyback    proc    near    uses ds
  1156. ;
  1157.     cld
  1158.     mov     dx,sortcount            ; ソートバッファ上のエントリ数
  1159.     mov     es,dirbuff
  1160.     mov     ds,sortbuff
  1161. ;   @do while,(dx,/=,0)
  1162. @d0023:
  1163.       or    dx,dx
  1164.       je    @d0024
  1165. ;       @if (byte ptr es:[0],=,0),S     ; ディレクトリバッファは空きエントリ?
  1166.           cmp   byte ptr es:[0],0
  1167.           jne   @i0062
  1168. ;           @if (byte ptr ds:[0],=,0e5h)   ; 名前の頭がE5なら、変換しておく
  1169.               cmp   byte ptr ds:[0],0e5h
  1170.               jne   @i0063
  1171.                 mov     byte ptr ds:[0],05h
  1172. ;           @ifend
  1173. @i0063:
  1174.             mov     cx,10h          ; コピー
  1175.             xor     si,si
  1176.             xor     di,di
  1177.           rep   movsw
  1178.             dec     dx              ; カウントダウン
  1179.             mov     si,ds           ; 次のソートバッファエントリへ
  1180.             lea     si,[si+2]
  1181.             mov     ds,si
  1182. ;       @ifend
  1183. @i0062:
  1184.         mov     si,es               ; 次のディレクトリバッファエントリへ
  1185.         lea     si,[si+2]
  1186.         mov     es,si
  1187. ;   @doend
  1188.       jmp   @d0023
  1189. @d0024:
  1190. ;
  1191.     mov     ax,seg sortbuff         ; ソートバッファの解放
  1192.     mov     ds,ax
  1193.     mov     es,sortbuff
  1194.     mov     ah,49h
  1195.     int     21h
  1196. ;
  1197.     ret
  1198. ;
  1199. copyback    endp
  1200. ;
  1201. ;------------------------------------------------------------------------------
  1202. ;
  1203. ;   filldeleted
  1204. ;       ディレクトリ中の削除エントリをクリアする
  1205. ;
  1206. ;   TYPE    near call
  1207. ;   IN      entrycount,dirbuff
  1208. ;   OUT     なし
  1209. ;   保存レジスタ    bx,bp,ds
  1210. ;
  1211. ;------------------------------------------------------------------------------
  1212. ;
  1213. filldeleted proc    near
  1214. ;
  1215.     cld
  1216.     mov     ax,0f6h                 ; 埋め込みデータの設定 
  1217.     mov     si,entrycount           ; ディレクトリの最終ポイント取得
  1218.     mov     dx,si
  1219.     shl     dx,1
  1220.     add     dx,dirbuff
  1221. ;   @do until
  1222. @d0025:
  1223.         sub     dx,2                ; 最終位置から先頭方向へ
  1224.         mov     es,dx
  1225. ;       @if (byte ptr es:[0],=,0),S ; 削除エントリ判定
  1226.           cmp   byte ptr es:[0],0
  1227.           jne   @i0064
  1228.             mov     es:[0],ah       ; 頭1バイト 0orE5
  1229.             mov     cx,1fh          ; 残り31バイトをF6で埋める
  1230.             mov     di,1
  1231.           rep   stosb
  1232. ;       @else                       ; 有効エントリが見つかったので
  1233.           jmp short @i0065
  1234. @i0064:
  1235.             mov     ah,0e5h         ; それ以後は頭1バイトをE5に変更
  1236. ;       @ifend
  1237. @i0065:
  1238.         dec     si
  1239. ;   @doend (si,=,0)                 ; ディレクトリ先頭になるまで
  1240.       or    si,si
  1241.       jne   @d0025
  1242.     ret
  1243. ;
  1244. filldeleted endp
  1245. ;
  1246. ;------------------------------------------------------------------------------
  1247. ;
  1248. ;   writerootdirectory
  1249. ;       ルートディレクトリバッファをファイルに書き戻す
  1250. ;
  1251. ;   TYPE    near call
  1252. ;   IN      dirtype,driveno,drvinf構造体,sectcount,clustcount,dirbuff
  1253. ;           clustsect,clustsize,subchain
  1254. ;   OUT     なし
  1255. ;   保存レジスタ
  1256. ;
  1257. ;------------------------------------------------------------------------------
  1258. ;
  1259. writerootdirectory  proc    near
  1260.     local wtsect:word,dirlen:word,buffseg:word,maxwtsect:word
  1261. ;
  1262.     mov     ax,drvinf.directorystart ; ルートディレクトリ書き込み
  1263.     mov     wtsect,ax               ; 書き込み開始セクタ番号
  1264.     mov     ax,sectcount
  1265.     mov     dirlen,ax               ; 残りディレクトリセクタ数
  1266.     mov     ax,dirbuff
  1267.     mov     buffseg,ax              ; 書き込みバッファセグメント
  1268.     mov     dx,1
  1269.     xor     ax,ax
  1270.     div     drvinf.sectorlength
  1271.     mov     maxwtsect,ax            ; 64KB当たりのセクタ数
  1272. ;   @do while,(dirlen,/=,0)         ; 書き込みループ 残りセクタ数0まで
  1273. @d0026:
  1274.       cmp   dirlen,0
  1275.       je    @d0027
  1276.         mov     ax,driveno
  1277.         mov     cx,maxwtsect
  1278. ;       @if (cx,<=,dirlen),S        ; 残りセクタ数が64KB以上なら
  1279.           cmp   cx,dirlen
  1280.           ja    @i0066
  1281.             sub     dirlen,cx       ; 残りセクタ数を更新
  1282. ;       @else                       ; 64KB未満なら
  1283.           jmp short @i0067
  1284. @i0066:
  1285.             xor     cx,cx           ; セクタ数を獲得してワークには0を入れる
  1286.             xchg    dirlen,cx
  1287. ;       @ifend
  1288. @i0067:
  1289.         mov     dx,wtsect           ; 開始セクタ数獲得
  1290.         push    bp                  ; 書き込み
  1291.         push    ds
  1292. ;       @if (sect32,=,NO),S         ; 従来の16bitセクタ番号
  1293.           cmp   sect32,NO
  1294.           jne   @i0068
  1295.             xor     bx,bx
  1296.             mov     ds,buffseg
  1297. ;       @else                       ; 新規の32bitセクタ番号
  1298.           jmp short @i0069
  1299. @i0068:
  1300.             mov     bx,offset diskaccs
  1301.             mov     word ptr [bx].sectornum,dx
  1302.             mov     word ptr [bx].sectornum+2,0
  1303.             mov     [bx].rwcount,cx
  1304.             mov     cx,buffseg
  1305.             mov     word ptr [bx].dskbuffer,0
  1306.             mov     word ptr [bx].dskbuffer+2,cx
  1307.             mov     cx,-1
  1308. ;       @ifend
  1309. @i0069:
  1310.         int     26h
  1311. ;       @if (cf,on)
  1312.           jnc   @i0070
  1313.             xor     cx,cx
  1314.             xor     dx,dx
  1315.             jmp     abort
  1316. ;       @ifend
  1317. @i0070:
  1318.         popf
  1319.         pop     ds
  1320.         pop     bp
  1321. ;
  1322.         mov     ax,maxwtsect        ; 書き込み開始セクタ数更新
  1323.         add     wtsect,ax
  1324.         add     buffseg,1000h       ; 書き込みバッファセグメント更新
  1325. ;   @doend
  1326.       jmp   @d0026
  1327. @d0027:
  1328.     ret
  1329. ;
  1330. writerootdirectory  endp
  1331. ;
  1332. ;------------------------------------------------------------------------------
  1333. ;
  1334. ;   writesubdirectory
  1335. ;       サブディレクトリバッファをファイルに書き戻す
  1336. ;
  1337. ;   TYPE    near call
  1338. ;   IN      dirtype,driveno,drvinf構造体,sectcount,clustcount,dirbuff
  1339. ;           clustsect,clustsize,subchain
  1340. ;   OUT     なし
  1341. ;   保存レジスタ
  1342. ;
  1343. ;------------------------------------------------------------------------------
  1344. ;
  1345. writesubdirectory  proc    near
  1346.         local cluster:word,clustseg:word
  1347. ;
  1348.     push    ds                  ; サブディレクトリ書き込み
  1349.     mov     ax,clustcount
  1350.     mov     cluster,ax
  1351.     mov     ax,clustsize
  1352.     mov     cl,4
  1353.     shr     ax,cl
  1354.     mov     clustseg,ax
  1355.     mov     di,offset subchain
  1356. ;   @if (sect32,=,NO)
  1357.       cmp   sect32,NO
  1358.       jne   @i0071
  1359.         mov     ax,ds
  1360.         mov     es,ax
  1361.         xor     bx,bx
  1362.         mov     ds,dirbuff
  1363. ;       @do until
  1364. @d0028:
  1365.             mov     ax,es:[di]
  1366.             sub     ax,2
  1367.             mov     cx,es:clustsect
  1368.             mul     cx
  1369.             add     ax,es:drvinf.datastartsector
  1370.             mov     dx,ax
  1371.             mov     ax,es:driveno
  1372.             push    bp
  1373.             push    di
  1374.             int     26h
  1375. ;           @if (cf,on)
  1376.               jnc   @i0072
  1377.                 xor     cx,cx
  1378.                 xor     dx,dx
  1379.                 jmp abort
  1380. ;           @ifend
  1381. @i0072:
  1382.             popf
  1383.             pop     di
  1384.             pop     bp
  1385.             mov     ax,ds
  1386.             add     ax,clustseg
  1387.             mov     ds,ax
  1388.             lea     di,[di+2]
  1389.             dec     cluster
  1390. ;       @doend (zf,on)
  1391.           jnz   @d0028
  1392.         pop     ds
  1393. ;   @else
  1394.       jmp   @i0073
  1395. @i0071:
  1396.         mov     ax,clustsect
  1397.         mov     diskaccs.rwcount,ax
  1398.         mov     ax,dirbuff
  1399.         mov     word ptr diskaccs.dskbuffer,0
  1400.         mov     word ptr diskaccs.dskbuffer+2,ax
  1401. ;       @do until
  1402. @d0029:
  1403.             mov     bx,offset diskaccs
  1404.             mov     ax,[di]             ; ディレクトリクラスタ書き込み
  1405.             sub     ax,2
  1406.             mov     cx,clustsect
  1407.             mul     cx
  1408.             add     ax,drvinf.datastartsector
  1409.             adc     dx,0
  1410.             mov     word ptr [bx].sectornum,ax
  1411.             mov     word ptr [bx].sectornum+2,dx
  1412.             mov     ax,driveno
  1413.             mov     cx,-1
  1414.             push    bp
  1415.             push    di
  1416.             int     26h
  1417. ;           @if (cf,on)
  1418.               jnc   @i0074
  1419.                 xor     cx,cx
  1420.                 xor     dx,dx
  1421.                 jmp     abort
  1422. ;           @ifend
  1423. @i0074:
  1424.             popf
  1425.             pop     di
  1426.             pop     bp
  1427.             mov     ax,clustseg
  1428.             add     word ptr diskaccs.dskbuffer+2,ax ; 次のバッファセグメント
  1429.             lea     di,[di+2]                      ; 次のクラスタ
  1430.             dec     cluster                        ; カウントダウン
  1431. ;       @doend (zf,on)
  1432.           jnz   @d0029
  1433. ;   @ifend
  1434. @i0073:
  1435.     ret
  1436. ;
  1437. writesubdirectory  endp
  1438. ;
  1439. ;------------------------------------------------------------------------------
  1440. ;
  1441. ;   dspdirname
  1442. ;       処理中ディレクトリ名を表示する
  1443. ;
  1444. ;   TYPE    near call
  1445. ;   IN      ES:DI ディレクトリ名文字列アドレス
  1446. ;   OUT     なし
  1447. ;   保存レジスタ    DS
  1448. ;
  1449. ;------------------------------------------------------------------------------
  1450. ;
  1451. dspdirname  proc
  1452. ;
  1453.     mov     ah,9        ; 処理中メッセージ表示
  1454.     mov     dx,offset procs
  1455.     int     21h
  1456. ;
  1457.     cld                             ; ディレクトリ名長さを獲得
  1458.     mov     cx,-1
  1459.     xor     ax,ax
  1460.     mov     dx,di
  1461.   repne     scasb
  1462.     not     cx
  1463.     dec     cx
  1464. ;
  1465.     push    ds                      ; ディレクトリ名表示
  1466.     mov     ax,es
  1467.     mov     ds,ax
  1468.     call    dosstdout
  1469.     pop     ds
  1470. ;
  1471.     mov     ah,2                ; 行頭への復帰
  1472.     mov     dl,0dh
  1473.     int     21h
  1474. ;
  1475.     ret
  1476. ;
  1477. dspdirname  endp
  1478. ;
  1479. ;------------------------------------------------------------------------------
  1480. ;
  1481. ;   dspmsgend
  1482. ;       処理終了メッセージを表示する
  1483. ;
  1484. ;   TYPE    near call
  1485. ;   IN      sortcount,movecount,sortproc,sweep
  1486. ;   OUT     なし
  1487. ;   保存レジスタ    ax,bx,cx,dx,si,di,bp,ds,es
  1488. ;
  1489. ;------------------------------------------------------------------------------
  1490. ;
  1491. dspmsgend   proc    uses ax bx cx dx si di ds es
  1492.         local   wrks:dword,wrka:word
  1493. ;
  1494.     mov     ax,sortcount            ; ソートしたエントリ数
  1495.     mov     bx,movecount            ; 移動したエントリ数
  1496.     mov     cx,ax
  1497.     add     cx,bx
  1498. ;   @cbegin
  1499. ;   @case (sortexec,=,YES),and,(sweep,=,YES),and,(cx,/=,0),S ; ソート&移動
  1500.       cmp   sortexec,YES
  1501.       jne   @c0005
  1502.       cmp   sweep,YES
  1503.       jne   @c0005
  1504.       or    cx,cx
  1505.       je    @c0005
  1506.         mov     ax,cx
  1507.         mov     si,offset bothmsg
  1508. ;   @case (sortexec,=,YES),and,(sweep,=,NO),and,(ax,/=,0),S ; ソートのみ
  1509.       jmp short @c0004
  1510. @c0005:
  1511.       cmp   sortexec,YES
  1512.       jne   @c0006
  1513.       cmp   sweep,NO
  1514.       jne   @c0006
  1515.       or    ax,ax
  1516.       je    @c0006
  1517. ;       @if (ax,>,1),S
  1518.           cmp   ax,1
  1519.           jbe   @i0075
  1520.             mov     si,offset sortmsg   ; 2つ以上ならソートのみ表示
  1521. ;       @else
  1522.           jmp short @i0076
  1523. @i0075:
  1524.             mov     si,offset bothmsg   ; 1つだけならソート&移動表示
  1525. ;       @ifend
  1526. @i0076:
  1527. ;   @case (sortexec,=,NO),and,(sweep,=,YES),and,(bx,/=,0),S ; 移動のみ
  1528.       jmp short @c0004
  1529. @c0006:
  1530.       cmp   sortexec,NO
  1531.       jne   @c0007
  1532.       cmp   sweep,YES
  1533.       jne   @c0007
  1534.       or    bx,bx
  1535.       je    @c0007
  1536.         mov     ax,cx
  1537.         mov     si,offset movemsg   ; 移動
  1538. ;   @other
  1539.       jmp short @c0004
  1540. @c0007:
  1541.         xor     ax,ax
  1542.         mov     si,offset nothmsg   ; 対象なし
  1543. ;   @cend
  1544. @c0004:
  1545. ;   @if (ax,/=,0)
  1546.       or    ax,ax
  1547.       je    @i0077
  1548.         mov     di,ss               ; 処理したエントリ数表示
  1549.         mov     es,di
  1550.         lea     di,offset wrka+1
  1551.         call    inttoasc0
  1552.         lea     di,[di-5]           ; 0サプレス処理
  1553.         push    di
  1554.         mov     cx,4
  1555. ;       @do while,(byte ptr es:[di],=,'0'),and,(cx,/=,0)
  1556. @d0030:
  1557.           cmp   byte ptr es:[di],'0'
  1558.           jne   @d0031
  1559.           or    cx,cx
  1560.           je    @d0031
  1561.             mov     byte ptr es:[di],' '
  1562.             inc     di
  1563.             dec     cx
  1564. ;       @doend
  1565.           jmp   @d0030
  1566. @d0031:
  1567.         mov     cx,5                ; エントリ数表示
  1568.         pop     dx
  1569.         mov     di,ds
  1570.         push    ss
  1571.         pop     ds
  1572.         call    dosstdout
  1573.         mov     ds,di
  1574. ;   @ifend
  1575. @i0077:
  1576.     mov     ah,9                    ; エントリ数に続くメッセージ表示
  1577.     mov     dx,si
  1578.     int     21h
  1579.     ret
  1580. ;
  1581. dspmsgend   endp
  1582. ;
  1583. ;------------------------------------------------------------------------------
  1584. ;
  1585. ;   altint23h
  1586. ;       Ctrl+C押下の横取り
  1587. ;
  1588. ;   TYPE    interrupt
  1589. ;   IN      なし
  1590. ;   OUT     なし
  1591. ;   保存レジスタ    ax,bx,cx,dx,si,di,bp,ds,es
  1592. ;
  1593. ;------------------------------------------------------------------------------
  1594. ;
  1595. altint23h   proc
  1596. ;
  1597. ;   @if (cs:critical,=,NO),S        ; クリティカルセクションではない時
  1598.       cmp   cs:critical,NO
  1599.       jne   @i0078
  1600.         jmp     cs:orgint23h        ; 既存の終了処理へ
  1601. ;   @else                           ; クリティカルセクションの時
  1602.       jmp short @i0079
  1603. @i0078:
  1604.         mov     cs:breakflag,YES    ; Ctrl+C押下を記憶しただけで復帰
  1605.         iret
  1606. ;   @ifend
  1607. @i0079:
  1608. ;
  1609. altint23h   endp
  1610. ;
  1611.         end     main
  1612.